#include "stdafx.h"

void Trigger::UpdatePrice(System::Object^ sender, AxTWSLib::_DTwsEvents_tickPriceEvent^ e)
{
	if (e->tickType == 4 && onlineLastID == e->id)
	{
		onlineLast = e->price;
		if (triggerIsActive == true && (   (Trend == sLONG && Math::Round((double)onlineLast, 2) < Math::Round((double)stopLossPrice, 2)) || (Trend == sSHORT && Math::Round((double)onlineLast, 2) > Math::Round((double)stopLossPrice, 2))   ))
		{
			GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + symbolName + " - Trigger Canceled, reach stop before");
			CloseTrigger(false);
		}

		if (triggerIsActive == false && stopIsActive == true  && (   (Trend == sLONG && Math::Round((double)onlineLast, 2) < Math::Round((double)stopLossPrice, 2)) || (Trend == sSHORT && Math::Round((double)onlineLast, 2) > Math::Round((double)stopLossPrice, 2))   ))
		{
			GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + symbolName + " - Reach StopLoss!");
			CloseTrigger(false);
		}
	}
}

void Trigger::TriggerFilled(System::Object^ sender, AxTWSLib::_DTwsEvents_orderStatusEvent^ e)
{
	if ( (e->status == "Filled" || e->status == "Submitted") && e->id == triggerOrderID )
	{
		quantityFilled = e->filled;
		LimitP->CalculateSizes();
		if (triggerIsActive == true && quantityFilled > 0)
		{
			GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - Order Activated (" + e->filled + " quantities filled" + (e->remaining == 0 ? ")" : " so far)") );
			triggerIsActive = false;
			tmr.Tag = "first";
			tmr.Enabled = true;
			return;
		}
		if (triggerIsActive == false && quantityFilled > 0 && tmr.Enabled == false)
		{
			GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - Order Updated (" + e->filled + " quantities filled" + (e->remaining == 0 ? ")" : " so far)") );
			tmr.Tag = "update";
			tmr.Enabled = true;
		}
	}
	if ( (e->status == "Filled" || e->status == "Submitted") && e->id == limit_1_OrderID )
	{
		if (e->status == "Filled" && LimitP->Profit_1_filled != e->filled) GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - Limit 1 Reached (" + e->filled + " quantities filled)");
		LimitP->Profit_1_filled = e->filled;
	}
	if ( (e->status == "Filled" || e->status == "Submitted") && e->id == limit_2_OrderID )
	{
		if (e->status == "Filled" && LimitP->Profit_2_filled != e->filled) GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - Limit 2 Reached (" + e->filled + " quantities filled)");
		LimitP->Profit_2_filled = e->filled;
	}
	if ( (e->status == "Filled" || e->status == "Submitted") && e->id == limit_3_OrderID )
	{
		if (e->status == "Filled" && LimitP->Profit_3_filled != e->filled) GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - Limit 3 Reached (" + e->filled + " quantities filled)");
		LimitP->Profit_3_filled = e->filled;
	}
	if ( (e->status == "Filled" || e->status == "Submitted") && e->id == limit_4_OrderID )
	{
		if (e->status == "Filled" && LimitP->Profit_4_filled != e->filled) GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - Limit 4 Reached (" + e->filled + " quantities filled)");
		LimitP->Profit_4_filled = e->filled;
	}
}

void Trigger::PerformLimits(System::Object^ sender, System::EventArgs^ e)
{
	if (tmr.Tag == "first")
	{
		account->TwsPointer->NewOrder(this, oLimit_1);
		if (LimitP->Profit_2_price != 0) account->TwsPointer->NewOrder(this, oLimit_2);
		if (LimitP->Profit_3_price != 0) account->TwsPointer->NewOrder(this, oLimit_3);
		if (LimitP->Profit_4_price != 0) account->TwsPointer->NewOrder(this, oLimit_4);
	}
	if (tmr.Tag == "update")
	{
		account->TwsPointer->UpdateOrder(this, oLimit_1);
		if (LimitP->Profit_2_price != 0) account->TwsPointer->UpdateOrder(this, oLimit_2);
		if (LimitP->Profit_3_price != 0) account->TwsPointer->UpdateOrder(this, oLimit_3);
		if (LimitP->Profit_4_price != 0) account->TwsPointer->UpdateOrder(this, oLimit_4);
	}

	tmr.Enabled = false;
}

void Trigger::CloseTrigger(bool StopInMKT)
{
	if (StopInMKT == true && stopOrderID != NULL && stopMktPerformed == false)
	{
		stopMktPerformed = true;
		account->TwsPointer->CancelOrder(stopOrderID);
		account->TwsPointer->NewOrder(this, oStopMKT);
	}

	if (inActive == true) return;
	inActive = true;

	if (triggerIsActive == true)
	{
		account->TwsPointer->CancelOrder(triggerOrderID);
		triggerIsActive = false;
		stopIsActive = false;
	}
	if (triggerIsActive == false && stopIsActive == true)
	{
		if (Quantity != QuantityFilled) account->TwsPointer->CancelOrder(triggerOrderID);
		stopIsActive = false;

		if (limit_1_OrderID != NULL) { account->TwsPointer->CancelOrder(limit_1_OrderID); limit_1_OrderID = -1; }
		if (limit_2_OrderID != NULL) { account->TwsPointer->CancelOrder(limit_2_OrderID); limit_2_OrderID = -1; }
		if (limit_3_OrderID != NULL) { account->TwsPointer->CancelOrder(limit_3_OrderID); limit_3_OrderID = -1; }
		if (limit_4_OrderID != NULL) { account->TwsPointer->CancelOrder(limit_4_OrderID); limit_4_OrderID = -1; }
		(StopInMKT == true) ? account->TwsPointer->NewOrder(this, oStopMKT) : account->TwsPointer->NewOrder(this, oStop);
	}
}

Trigger::Trigger(System::String ^symName, float trgPrice, float stpCents, int qSize, Side sd, Account ^acc, Bars ^br)
{
	acc->Tws->orderStatus += gcnew AxTWSLib::_DTwsEvents_orderStatusEventHandler(this, &Trigger::TriggerFilled);
	account = acc;
	bars = br;
	limit = gcnew Limit(this, account);
	symbolName = symName;
	triggerPrice = trgPrice;
	stopLossCents = stpCents;


	triggerSpread = (int)(stpCents * 10);
	triggerSpread /= 100;
	if (triggerSpread == 0) triggerSpread = 0.01;
	triggerSpread += account->LimitOptions->optTriggerSpread;
	side = sd;

	if (sd == sLONG)
	{
		stopLossPrice = trgPrice - stopLossCents;
		triggerStopPrice = triggerPrice;
		triggerLimitPrice = triggerStopPrice + triggerSpread;
		riskByCents = triggerLimitPrice - stopLossPrice;
		quantity = qSize;
	}
	if (sd == sSHORT)
	{
		stopLossPrice = trgPrice + stopLossCents;
		triggerStopPrice = triggerPrice;
		triggerLimitPrice = triggerStopPrice - triggerSpread;
		riskByCents = stopLossPrice - triggerLimitPrice;
		quantity = qSize;
	}

	quantity = (quantity / 10) * 10;

	tideStop = account->LimitOptions->optTideStop;
	tideStopSpace = account->LimitOptions->optTideStopSpace;
	tideStopStartAfter = account->LimitOptions->optTideStopStartAfter;
	triggerSpread = account->LimitOptions->optTriggerSpread;
	stopLossSpread = account->LimitOptions->optStopLossSpread;
	roundANumber = account->LimitOptions->optRoundANumber;
	roundStopNumber = account->LimitOptions->optRoundStopNumber;

	limit->UpdateProfits(true);
	originalStopLossPrice = stopLossPrice;

	triggerOrderID = NULL;
	triggerIsActive = true;
	stopOrderID = NULL;
	stopIsActive = true;
	stopMktPerformed = false;
	limit_1_OrderID = NULL;
	limit_2_OrderID = NULL;
	limit_3_OrderID = NULL;
	limit_4_OrderID = NULL;

	acc->TwsPointer->NewOrder(this, oTrigger);

	TWSLib::IContract ^ic;
	ic = acc->TwsPointer->CreateContract();

	ic->symbol = symName;
	ic->exchange = "SMART";
	ic->currency = "USD";
	ic->secType = "STK";
	onlineLastID = acc->TwsPointer->GetNewID();

	acc->Tws->tickPrice += gcnew AxTWSLib::_DTwsEvents_tickPriceEventHandler(this, &Trigger::UpdatePrice);
	acc->Tws->reqMktDataEx(onlineLastID, ic, "", 0);

	tmr.Enabled = false;
	tmr.Interval = 2000;
	tmr.Tick += gcnew System::EventHandler(this, &Trigger::PerformLimits);

	inActive = false;
}